/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package Data;

import java.util.ArrayList;
import java.util.Arrays;
import javax.swing.table.DefaultTableModel;


/**
 *
 * @author rjimenez
 */
public class TablaSimbolos {

    ArrayList<Sim> tabla = new ArrayList<Sim>();
    Sim sim=null;

    public TablaSimbolos() {
    }
    
    
    


    public void Insertar(Sim nuevo, Token tok)
    {
        
        if(!CompararAmbito(nuevo))
        {
            tabla.add(nuevo);
        }
        else
        {
            System.out.println("ya existe el simbolo "+ tok.getLexema());
        }
        
    }
    
    
    public boolean Insertar(Sim nuevo)
    {
        
        if(!CompararAmbito(nuevo))
        {
            tabla.add(nuevo);
            return false;
        }
        else
        {
            return true;
        }
        
    }



    boolean CompararAmbito(Sim nuevo)
    {
        boolean yaexiste=false;
        int numambitos;
        int varambitos;
        String auxambito;
        String ambitoactual;
        String ambitos[];
        String ambitossim[];

        if(nuevo.getRol().equals("parametro"))
        {
            return yaexiste;
        }
        else
        {

            ambitos = nuevo.getAmbito().split("/");
            numambitos = ambitos.length;


            //recorrer los ambitos desde el ultimo hasta el padre
            for(int i=numambitos-1; i>=0;i--)
            {
                ambitoactual = ambitos[i];
                
                for(Sim simbolo: tabla)//recorremos la tabla
                {
                    ambitossim = simbolo.getAmbito().split("/");
                    varambitos = ambitossim.length;

                    if(varambitos > numambitos) //solo ambitos de niveles iguales o menores
                    {
                        System.out.println("ambito de mas niveles que el actual");
                    }
                    else
                    {
                           
                        
                       

                        if(varambitos-1==i)//buscamos solo en ambitos del mismo nivel
                        {
                            if(ambitoactual.equals(ambitossim[i])) //comparamos que los ambitos sean los mismo
                            {


                                    if(simbolo.getNombre().equals(nuevo.getNombre()))//comparamos si la variable ya existe
                                    {
                                        
                                        if(simbolo.getRol().equals("funcion"))//comparamos si es funcion
                                        {
                                            if(simbolo.getNumparams()==nuevo.getNumparams())//si tiene los mismos parametros
                                            {
                                                if(simbolo.getParams().equals(nuevo.getParams()))//si los tipos de los parametros son los mismos
                                                {
                                                    yaexiste = true;
                                                    return yaexiste;
                                                }
                                            }
                                        }
                                        else if(simbolo.getRol().compareTo("clase")==0 && nuevo.getRol().compareTo("funcion")==0)
                                        {
                                            if(simbolo.getNombre().compareTo(nuevo.getAmbito().split("/")[1])==0)
                                            {
                                                return yaexiste;
                                            }
                                        }
                                        else{
                                            yaexiste = true;
                                            return yaexiste;
                                            
                                        }
                                        
                                    }

                            }
                            else
                            {
                                System.out.println("ambito diferente");
                            }
                        }

                        
                    }

                }
            }



        }


        return yaexiste;
    }


    public Sim BuscarSim(String var)
    {
        Sim encontrado=null;

        for(Sim simbolo: tabla)
        {
            if(simbolo.getNombre().equals(var))
            {
                encontrado = simbolo;
                break;
            }
        }


        return encontrado;
    }

    public Sim BuscarFuncion(String fun)
    {
        Sim encontrado=null;

        for(Sim simbolo: tabla)
        {
            if(simbolo.getNombre().equals(fun)&& simbolo.getRol().equals("funcion"))
            {
                encontrado = simbolo;
                break;
            }
        }


        return encontrado;
    }
    
    public int BuscarNumFuncion(String fun)
    {
        int res = -1;

        int cont =0;
        for(Sim simbolo: tabla)
        {
            if(simbolo.getNombre().equals(fun)&& simbolo.getRol().equals("funcion"))
            {
                res = cont;
                break;
            }
            
            cont++;
        }


        return res;
    }


    public boolean NumParametros(Sim fun,int par)
    {
        Sim aux;
       

        aux = fun;
        
        if(aux.getNumparams()==par)
        {
            return true;
        }
        else
        {
            return false;
        }
        
                
    }

    public boolean TipoParametros(Sim fun,String  par)
    {
        Sim aux;
     

        aux = fun;

        if(aux.getParams().equals(par))
        {
            return true;
        }
        else
        {
            return false;
        }


    }


    public int BuscarAmbito(String ambitoactual, String var)
    {
        Sim aux;
        int ambact;
        int ambvar;
        String ambitovar[];
        String ambitoaux[];
        String ambitoact[];
        int res =-2;
        sim = null;
        
        for(Sim simbolo: tabla)
        {
            if(simbolo.getNombre().equals(var))
            {
                aux = simbolo;
                
                if(aux!=null)
                {
//                     if(aux.getRol().equals(""))
                      ambitovar = aux.getAmbito().split("/");
                      ambitoact = ambitoactual.split("/");
                      ambact = ambitoact.length;
                      ambvar = ambitovar.length;

                    if(!(ambvar>ambact))
                    {
                        for(int i=ambact-1; i>=0;i--)
                        {
                           ambitoaux = Arrays.copyOf(ambitoact, i+1);

                           if(Arrays.equals(ambitoaux, ambitovar))
                           {
                               System.out.println("puede utilizarse");
                               res =0;
                               sim = aux;
                               break;
                           }


                        }
                    }
                    else
                    {
                        res=-2;
                        System.out.println("ambito distinto");
                    }

                }
                else
                {
                    res=-1;
                    System.out.println("no existe la variable");
                }
            }
        }

        

        return res;
    }

    
    public int ObtenerTipo(String ambitoactual,String var)
    {
        int tipo;
        int op;
        
        op =BuscarAmbito(ambitoactual, var);

        if(op==0)
        {
            if(sim!=null)
            {
                tipo = sim.getTipo();
                return tipo;
            }
            else
            {
                return -2;
            }
            
        }
        else
        {
            return op;
        }
        
       
    }

    
    
    public Sim ObtenerSimbolo(String ambitoactual,String var)
    {
        Sim aux=null;
        int op;

        op =BuscarAmbito(ambitoactual, var);

        if(op==0)
        {
            if(sim!=null)
            {
                aux = sim;
                return aux;
            }
            else {
                return null;
            }
            
        }
        else
        {
            return null;
        }


    }


    public int ObtenerPosPila(String ambitoactual,String var)
    {
        int pila;
        int op;

        op =BuscarAmbito(ambitoactual, var);

        if(op==0)
        {
            pila = sim.getPospila();
            return pila;
        }
        else
        {
            return op;
        }


    }
    
    public Sim BuscarArreglo(String arr)
    {
        Sim encontrado=null;

        for(Sim simbolo: tabla)
        {
            if(simbolo.getNombre().equals(arr)&& simbolo.getRol().equals("arreglo"))
            {
                encontrado = simbolo;
                break;
            }
        }


        return encontrado;
    }
    
    public String SizeDimension(String arr, int dim)
    {
        int ind;
        String dimen="";
        Sim aux;
        ArrayList<String> dims;
        
        aux = BuscarArreglo(arr);
        
        if(aux!=null)
        {
            dims = aux.getTam_dimensiones();
            
            if(dim<=dims.size())
            {
                ind = dim-1;
                dimen = dims.get(ind);
            }
        }
        
        return dimen;
    }

    public Sim BuscarClase(String clase)
    {
        Sim encontrado=null;

        for(Sim simbolo: tabla)
        {
            if(simbolo.getNombre().equals(clase)&& simbolo.getRol().equals("clase"))
            {
                encontrado = simbolo;
                break;
            }
        }


        return encontrado;
    }

    public ArrayList<Sim> getTabla() {
        return tabla;
    }

    public void setTabla(ArrayList<Sim> tabla) {
        this.tabla = tabla;
    }
    

    public DefaultTableModel getDtm()
    {
        
        String [] titulos= {"Nombre","Tipo","Ambito","Rol","Visibilidad","Dimensiones","Tamaño","Num. Parametros","Tipo Parametros",
                            "Posicion Pila","Posicion","instancia"};
        DefaultTableModel dtm = new DefaultTableModel(null,titulos);
        
        
        

        for(Sim simbolo: tabla)
        {
            Object data[] = {simbolo.getNombre(),simbolo.getTipo(),simbolo.getAmbito(),simbolo.getRol(),
                             simbolo.getVisibilidad(),simbolo.getDimensiones(),simbolo.getSize(),simbolo.getNumparams(),
                             simbolo.getParams(),simbolo.getPospila(),simbolo.getPos(),simbolo.getInstancia()};
            
            dtm.addRow(data);
        }
        
        
        
        return dtm;
    }
    

    public Sim getSim(int i)
    {
        return tabla.get(i);
    }
    
    
    public Sim BuscarInstancia(String clase, String var)
    {
        String ambito = "global/"+clase;
        Sim aux = null;
        
        for(Sim simbolo: tabla)
        {
            if(simbolo.getAmbito().equals(ambito)&& simbolo.getRol().equals("variable de clase"))
            {
                if(simbolo.getNombre().equals(var))
                {
                    aux = simbolo;
                    return aux;
                }
            }
        }
        
        return aux;
    }
   
}
